﻿using OpenCvSharp;
using OpenCvSharp.WpfExtensions;
using PLCSharp.CoreModel.Common;
using PLCSharp.CoreModel.Prism;
using PLCSharp.Views.Vision.Camera;
using Prism.Commands;
using Prism.Dialogs;
using Prism.Events;
using Prism.Ioc;
using System.Threading;
using System.Windows.Media.Imaging;

namespace PLCSharp.Views.Vision
{
    public class VisionsViewModel : DialogAwareBase
    {


        public VisionsViewModel(IContainerExtension container, IEventAggregator ea, IDialogService dialogService) : base(container, ea, dialogService)
        {

            VisionsModel = container.Resolve<VisionsModel>();

        }
        public VisionsModel VisionsModel { get; }

        private Mat _ShowMat;
        /// <summary>
        /// 
        /// </summary>
        public Mat ShowMat
        {
            get { return _ShowMat; }
            set
            {
                SetProperty(ref _ShowMat, value);
                if (value == null) return;
                System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                {
                    if (_ImgSrc != null
                    && _ShowMat.Width == _ImgSrc.PixelWidth
                    && _ShowMat.Height == _ImgSrc.PixelHeight)
                    {
                        WriteableBitmapConverter.ToWriteableBitmap(_ShowMat, _ImgSrc);

                    }
                    else
                    {
                        ImgSrc = _ShowMat.ToWriteableBitmap();
                    }
                }));


            }
        }
        private WriteableBitmap _ImgSrc;

        public WriteableBitmap ImgSrc
        {
            get { return _ImgSrc; }
            set { SetProperty(ref _ImgSrc, value); }
        }

        private CameraBase _Camera;
        /// <summary>
        /// Comment
        /// </summary>
        public CameraBase Camera
        {
            get { return _Camera; }
            set
            {
                if (cameraWorking) return;

                SetProperty(ref _Camera, value);
            }
        }

        private DelegateCommand _SearchCameras;
        public DelegateCommand SearchCameras =>
            _SearchCameras ??= new DelegateCommand(ExecuteSearchCameras);

        void ExecuteSearchCameras()
        {
            VisionsModel.SearchCameras();
        }

        private DelegateCommand _AddCameras;
        public DelegateCommand AddCameras =>
            _AddCameras ??= new DelegateCommand(ExecuteAddCameras);

        void ExecuteAddCameras()
        {
            if (Camera == null) return;
            var camera = VisionsModel.Cameras.Where(c => c.Name == Camera.Name).FirstOrDefault();
            if (camera == null)
            {
                VisionsModel.Cameras.Add(Camera);

            }
            else
            {
                SendErr("相机已存在", ErrType.ShowDialog);
            }


        }
        private DelegateCommand _StopContinuous;
        public DelegateCommand StopContinuous =>
            _StopContinuous ??= new DelegateCommand(ExecuteStopContinuous);

        void ExecuteStopContinuous()
        {
            Camera.StopContinuous();
            continuous = false;

        }
        bool continuous;
        private AsyncDelegateCommand<object> _CameraCommand;
        public AsyncDelegateCommand<object> CameraCommand =>
            _CameraCommand ??= new AsyncDelegateCommand<object>(ExecuteCameraCommandAsync);

        private async Task ExecuteCameraCommandAsync(object param)
        {
            if (Camera is null) return;
            var cmd = param as string;


            if (cameraWorking) return;
            cameraWorking = true;
            await Task.Run(() =>
            {

                FlowModel flow = new();
                switch (cmd)
                {
                    case "Trig":
                        {
                            while (flow.Done == false)
                            {
                                Thread.Sleep(1);
                                switch (flow.Step)
                                {
                                    case 0:
                                        Camera.SoftwareTrig();

                                        flow.Step++;
                                        break;
                                    case 1:
                                        if (Camera.WaitOne())
                                        {
                                            ShowMat = Camera.Mat;
                                            flow.Step++;
                                        }

                                        break;
                                    case 2:
                                        Camera.SetTriggerSource();

                                        flow.Done = true;
                                        break;

                                }
                                if (flow.CheckFlowTime(10))
                                {

                                    break;
                                }
                            }

                        }
                        break;
                    case "Continuous":
                        {
                            while (flow.Done == false)
                            {
                                Thread.Sleep(1);
                                switch (flow.Step)
                                {
                                    case 0:
                                        Camera.Continuous();
                                        continuous = true;
                                        flow.Step++;
                                        break;
                                    case 1:
                                        if (Camera.WaitOne())
                                        {
                                            ShowMat = Camera.Mat;

                                        }
                                        if (continuous == false)
                                        {

                                            flow.Step++;
                                        }
                                        break;
                                    case 2:
                                        Camera.SetTriggerSource();

                                        flow.Done = true;
                                        break;

                                }

                            }

                        }
                        break;
                }


            });
            cameraWorking = false;
        }
        bool cameraWorking;
    }
}